#include "cameraCtrl.hpp"
#include <QtMath>
#include <QKeyEvent>

Camera::Camera(QVector3D position, QVector3D up, float yaw, float pitch)
    : _position(position), _worldUp(up), _yaw(yaw), _pitch(pitch),
      _movementSpeed(2.5f), _mouseSensitivity(0.1f), _fov(45.0f) {
    updateCameraVectors();
}

QMatrix4x4 Camera::getViewMatrix() {
    QMatrix4x4 view;
    view.lookAt(_position, _position + _front, _up);
    return view;
}

QMatrix4x4 Camera::getProjectionMatrix(float aspect, float near, float far) {
    QMatrix4x4 projection;
    projection.perspective(_fov, aspect, near, far);
    return projection;
}

void Camera::processKeyboard(int key, float deltaTime) {
    float velocity = _movementSpeed * deltaTime;
    
    switch(key) {
        case Qt::Key_W:
            _position += _front * velocity;
            break;
        case Qt::Key_S:
            _position -= _front * velocity;
            break;
        case Qt::Key_A:
            _position -= _right * velocity;
            break;
        case Qt::Key_D:
            _position += _right * velocity;
            break;
        case Qt::Key_Q:
            _position += _up * velocity;
            break;
        case Qt::Key_E:
            _position -= _up * velocity;
            break;
    }
}

void Camera::processMouseMovement(float xoffset, float yoffset, bool constrainPitch) {
    xoffset *= _mouseSensitivity;
    yoffset *= _mouseSensitivity;
    
    _yaw += xoffset;
    _pitch += yoffset;
    
    // 限制俯仰角
    if (constrainPitch) {
        if (_pitch > 89.0f) _pitch = 89.0f;
        if (_pitch < -89.0f) _pitch = -89.0f;
    }
    
    updateCameraVectors();
}

void Camera::processMouseScroll(float yoffset) {
    _fov -= yoffset;
    if (_fov < 1.0f) _fov = 1.0f;
    if (_fov > 45.0f) _fov = 45.0f;
}

void Camera::updateCameraVectors() {
    // 计算新的front向量
    QVector3D front;
    front.setX(cos(qDegreesToRadians(_yaw)) * cos(qDegreesToRadians(_pitch)));
    front.setY(sin(qDegreesToRadians(_pitch)));
    front.setZ(sin(qDegreesToRadians(_yaw)) * cos(qDegreesToRadians(_pitch)));
    _front = front.normalized();
    
    // 重新计算right和up向量
    _right = QVector3D::crossProduct(_front, _worldUp).normalized();
    _up = QVector3D::crossProduct(_right, _front).normalized();

}